#include <stdio.h>
#include "HskUtil.h"
#include "HskVector.h"
#include "HskBuffer.h"

void PrintLongLongFun (Vector *const _this, void *data, size_t seq) {
  printf("%zu: %lld\n", seq, *(long long *)data);
}

void LongLongFoo1 (Vector *const _this, void *data, size_t seq) {
  *(long long *)data = seq * 7;
}

void CharUpper (Buffer *const _this, char *data, size_t seq) {
  if (97 <= *data && *data <= 122)
    *data -= 32;
}

int main() {
  printf("\n--- Create Vector vec1 whose capacity is 2 ---\n\n");
  Vector *vec1 = VecCreate(sizeof(long long), 0, 2);
  // 显示vec1的信息
  VecDispMsg(vec1);                       // expected: this.size = 0, this.capa = 2, this.typesize = 8.
  // 显示容器里的元素
  VecHandleAll(vec1, PrintLongLongFun);   // expected: 

  printf("\n--- Push 114, 514 into vec1 ---\n\n");
  long long num = 114;
  VecPush(vec1, &num);
  num = 514;
  VecPush(vec1, &num);
  VecDispMsg(vec1);                       // expected: this.size = 2, this.capa = 2, this.typesize = 8.
  VecHandleAll(vec1, PrintLongLongFun);   // expected: 0: 114
                                          // expected: 1: 514

  printf("\n--- Push 1919810 into vec1 ---\n\n");
  num = 1919810;
  VecPush(vec1, &num);
  VecDispMsg(vec1);                       // expected: this.size = 3, this.capa = 4, this.typesize = 8.
  VecHandleAll(vec1, PrintLongLongFun);   // expected: 0: 114
                                          // expected: 1: 514
                                          // expected: 2: 1919810

  printf("\n--- Initialize vec2 with vec1 ---\n\n");
  Vector *vec2 = VecCreate(sizeof(long long), 0, VecGetSize(vec1));
  VecPushSlice(vec2, vec1->_begin, vec1->_end);
  VecDispMsg(vec2);                       // expected: this.size = 3, this.capa = 3, this.typesize = 8.
  VecHandleAll(vec2, PrintLongLongFun);   // expected: 0: 114
                                          // expected: 1: 514
                                          // expected: 2: 1919810

  printf("\n--- Append vec1 to vec2 ---\n\n");
  VecPushSlice(vec2, vec1->_begin, vec1->_end);
  VecDispMsg(vec2);                       // expected: this.size = 6, this.capa = 8, this.typesize = 8.
  VecHandleAll(vec2, PrintLongLongFun);   // expected: 0: 114
                                          // expected: 1: 514
                                          // expected: 2: 1919810
                                          // expected: 3: 114
                                          // expected: 4: 514
                                          // expected: 5: 1919810

  printf("\n--- Append vec1 to vec2 ---\n\n");
  VecPushSlice(vec2, vec1->_begin, vec1->_end);
  VecDispMsg(vec2);                       // expected: this.size = 9, this.capa = 16, this.typesize = 8.
  VecHandleAll(vec2, PrintLongLongFun);   // expected: 0: 114
                                          // expected: 1: 514
                                          // expected: 2: 1919810
                                          // expected: 3: 114
                                          // expected: 4: 514
                                          // expected: 5: 1919810
                                          // expected: 6: 114
                                          // expected: 7: 514
                                          // expected: 8: 1919810

  printf("\n--- Delete last 3 elements in vec2 ---\n\n");
  VecDelN(vec2, 3);
  VecDispMsg(vec2);                       // expected: this.size = 6, this.capa = 16, this.typesize = 8.
  VecHandleAll(vec2, PrintLongLongFun);   // expected: 0: 114
                                          // expected: 1: 514
                                          // expected: 2: 1919810
                                          // expected: 3: 114
                                          // expected: 4: 514
                                          // expected: 5: 1919810

  printf("\n--- make vec2's capacity suitable ---\n\n");
  VecReCapa(vec2, HskPower2Ceil(VecGetSize(vec2)));
  VecDispMsg(vec2);                       // expected: this.size = 6, this.capa = 8, this.typesize = 8.
  VecHandleAll(vec2, PrintLongLongFun);   // expected: 0: 114
                                          // expected: 1: 514
                                          // expected: 2: 1919810
                                          // expected: 3: 114
                                          // expected: 4: 514
                                          // expected: 5: 1919810

  printf("\n--- Append vec1[0:2] to vec2 ---\n\n");
  VecPushSlice(vec2, vec1->_begin, VecGet(vec1, 2));
  VecDispMsg(vec2);                       // expected: this.size = 8, this.capa = 8, this.typesize = 8.
  VecHandleAll(vec2, PrintLongLongFun);   // expected: 0: 114
                                          // expected: 1: 514
                                          // expected: 2: 1919810
                                          // expected: 3: 114
                                          // expected: 4: 514
                                          // expected: 5: 1919810
                                          // expected: 6: 114
                                          // expected: 7: 514

  printf("\n--- let vec[5] = 19260817 ---\n\n");
  *(long long*)VecGet(vec2, 5) = 19260817;
  VecDispMsg(vec2);                       // expected: this.size = 8, this.capa = 8, this.typesize = 8.
  VecHandleAll(vec2, PrintLongLongFun);   // expected: 0: 114
                                          // expected: 1: 514
                                          // expected: 2: 1919810
                                          // expected: 3: 114
                                          // expected: 4: 514
                                          // expected: 5: 19260817
                                          // expected: 6: 114
                                          // expected: 7: 514

  printf("\n--- Apply LongLongFoo1 to each of vec2 ---\n\n");
  VecHandleAll(vec2, LongLongFoo1);
  VecDispMsg(vec2);                       // expected: this.size = 8, this.capa = 8, this.typesize = 8.
  VecHandleAll(vec2, PrintLongLongFun);   // expected: 0: 0
                                          // expected: 1: 7
                                          // expected: 2: 14
                                          // expected: 3: 21
                                          // expected: 4: 28
                                          // expected: 5: 35
                                          // expected: 6: 42
                                          // expected: 7: 49

  printf("\n--- Create 2 Buffer, one contains 'Hello', other contains 'world!' ---\n\n");
  char hello[] = "Hello ";
  Buffer *buf1 = BufCreate(0);
  BufPushSlice(buf1, hello, hello + 6);
  BufDispMsg(buf1);                               // expected: this.unreadSize = 6, this.size = 6, this.capa = 8.
  BufDispAllChar(buf1, buf1->_read, buf1->_end);  // expected: Hello
  char world[] = "world!";
  Buffer *buf2 = BufCreate(0);
  BufPushSlice(buf2, world, world + sizeof(world));
  BufDispMsg(buf2);                               // expected: this.unreadSize = 7, this.size = 7, this.capa = 8.
  BufDispAllChar(buf2, buf2->_read, buf2->_end);  // expected: world!

  printf("\n---Read buf2 into buf1 ---\n\n");
  BufReadBuf(buf1, buf2, BufGetSize(buf2));
  BufDispMsg(buf1);                               // expected: this.unreadSize = 13, this.size = 13, this.capa = 16.
  BufDispAllChar(buf1, buf1->_read, buf1->_end);  // expected: Hello world!
  BufDispMsg(buf2);                               // expected: this.unreadSize = 0, this.size = 7, this.capa = 8.
  BufDispAllChar(buf2, buf2->_read, buf2->_end);  // expected: 
  BufDispAllChar(buf2, buf2->_begin, buf2->_end); // expected: world!

  printf("\n--- Push buf1 into buf2 ---\n\n");
  BufPushSlice(buf2, buf1->_begin, buf1->_end);
  BufDispMsg(buf2);                               // expected: this.unreadSize = 13, this.size = 13, this.capa = 16.
  BufDispAllChar(buf2, buf2->_begin, buf2->_end); // expected: Hello world!

  printf("\n--- Replace all lowercase characters of buf2 with uppercase characters ---\n\n");
  BufHandleAll(buf2, CharUpper);
  BufDispMsg(buf2);                               // expected: this.unreadSize = 13, this.size = 13, this.capa = 16.
  BufDispAllChar(buf2, buf2->_begin, buf2->_end); // expected: HELLO WORLD!

  printf("\n--- Delete last 5 elements in buf2 ---\n\n");
  BufDelN(buf2, 5);
  BufDispMsg(buf2);                               // expected: this.unreadSize = 13, this.size = 13, this.capa = 16.
  BufDispAllChar(buf2, buf2->_begin, buf2->_end); // expected: HELLO WO

  getchar();
  return 0;
}
